/* Include these
   #include <rid.h>
   #include <stdint.h>
   #include <time.h>
*/

/* Makes things work on switch case statements without issue */
#define W4_WHAT(VAL) ((uint8_t) (VAL))

/* W4 what values used to represent logic dealing with an uncertain world in
 * many ways. They are designed such that systems using them can learn and
 * change based upon new information and replace assumptions. While this system
 * is still bounded by what is known, it is not bound by the limitations of a
 * binary world view and can literally deal with the nuances of reason.
 */

/* justified */
#define	Improj  W4_WHAT(1)
#define	Falj    W4_WHAT(1 << 1)
#define	Nuaj    W4_WHAT(1 << 2)
#define	Truj    W4_WHAT(1 << 3)
/* assumed */
#define	Imprasu W4_WHAT(1 << 4)
#define	Falasu  W4_WHAT(1 << 5)
#define	Nuasu   W4_WHAT(1 << 6)
#define	Truasu  W4_WHAT(1 << 7)
/* justified or assumed */
#define	Justified W4_WHAT(0xf       )
#define	Assumed   W4_WHAT(~Justified)
/* except */
#define	Aimproj  W4_WHAT(~Improj )
#define	Afalj    W4_WHAT(~Falj   )
#define	Anuaj    W4_WHAT(~Nuaj   )
#define	Atruj    W4_WHAT(~Truj   )
#define	Aimprasu W4_WHAT(~Imprasu)
#define	Afalasu  W4_WHAT(~Falasu )
#define	Anuasu   W4_WHAT(~Nuasu  )
#define	Atruasu  W4_WHAT(~Truasu )
/* truth value */
#define	Improper W4_WHAT(Improj | Imprasu)
#define	False    W4_WHAT(Falj   | Falasu )
#define	Nuanced  W4_WHAT(Nuaj   | Nuasu  )
#define	True     W4_WHAT(Truj   | Truasu )
/* improper opposite */
#define	Proj   W4_WHAT(Justified & Aimproj  )
#define	Prasu  W4_WHAT(Assumed   & Aimprasu )
#define	Proper W4_WHAT(~Improper            )
/* false opposite */
#define	UnFalj   W4_WHAT(Justified & Afalj  )
#define	Unfalasu W4_WHAT(Assumed   & Afalasu)
#define	Unfalse  W4_WHAT(~False             )
/* nuanced opposite */
#define	Defij    W4_WHAT(Justified & Anuaj )
#define	Defasu   W4_WHAT(Assumed   & Anuasu)
#define	Definite W4_WHAT(~Nuanced          )
/* true opposite */
#define	Untruj   W4_WHAT(Justified & Atruj  )
#define	Untruasu W4_WHAT(Assumed   & Atruasu)
#define	Untrue   W4_WHAT(~True              )
/* logical */
#define	Logij    W4_WHAT(Falj    | Truj  )
#define	Logasu   W4_WHAT(Falasu  | Truasu)
#define	Logical  W4_WHAT(False   | True  )
/* illogical*/
#define	Illogij   W4_WHAT(Improj  | Nuaj )
#define	Illogasu  W4_WHAT(Imprasu | Nuasu)
#define	Illogical W4_WHAT(~Logical       )
/* possible */
#define	Possij   W4_WHAT(Nuaj      | Truj  )
#define	Possasu  W4_WHAT(Nuasu     | Truasu)
#define	Possible W4_WHAT(Nuanced   | True  )
/* impossible */
#define	Impossij   W4_WHAT(Improj  | Falj  )
#define	Impossasu  W4_WHAT(Imprasu | Falasu)
#define	Impossible W4_WHAT(~Possible       )
/* unknown */
#define	Unknown W4_WHAT(~0)

typedef struct {
	uint8_t what;
	struct timespec when;
	Rid where;
        Rid why;
} W4;

typedef uint8_t W4_ser[sizeof(uint8_t) + 2 * sizeof(uint64_t) +
		       2 * sizeof(Rid)];

typedef enum {
	W4_ONE_FIRST,
	W4_ONE_SECOND,
	W4_BOTH_FIRST,
	W4_BOTH_SECOND,
	W4_BOTH_SAME
} W4_relv;

void
w4_init(W4 *w, uint8_t what, struct timespec *when, Rid where, Rid why);

void
w4_now(W4 *w, uint8_t what, Rid where, Rid why);

void
w4_copy(W4 *des, W4 *src);

void
w4_ser(W4_ser ser, const W4 *w);

void
w4_deser(W4 *w, const W4_ser ser);

void
w4_not(W4 *ans, W4 *w, Rid where, Rid why);

void
w4_compl(W4 *ans, W4 *w, Rid where, Rid why);

W4_relv
w4_and(W4 *ans, W4 *w1, W4 *w2, Rid where, Rid why);

W4_relv
w4_or(W4 *ans, W4 *w1, W4 *w2, Rid where, Rid why);
